package org.ws.edu.task1.ikhmyz;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.ws.edu.task1.IConsoleHandler;

// TODO [DK] 21.02.2012: Здесь есть  реализация только для операций с двумя числами,
//для реаализации программы, которая так же может работать с большим колличеством переменных, 
//работать со скобками  используй алгоритм "Обратная польская запись" или используй парсинг с помощью regex
// TODO [DK] 21.02.2012: Нужно обработать ситуации когда пользователь введёт что-то лишнее, текст. 
//Для этого используй иключения и их обработку.
// TODO [DK] 21.02.2012: Добавил твою реализацию в unit тест ConsoleHandlerTest, тесты не проходят, глянь туда.

public class ConsoleHandlerKHMZ implements IConsoleHandler {
// TODO [DK] 21.02.2012: эти два объекта можно задать с модификаторами private static final
	Pattern num = Pattern.compile("[0-9]+");
	Pattern symb = Pattern.compile("[\\+\\-\\^\\/\\*\\!\\~]"); // use ~ symbol to find square root

	private final CalculatorKHMZ calc = new CalculatorKHMZ();

	@Override
	public String handle(String line) {
		// TODO [DK] 21.02.2012: Нет нужны в перменной s1, сразу передваай в методы переменную line
		String s1 = line;
		// TODO [DK] 21.02.2012: по code convenient нужно писать fSymb, то же самое и везде внизу в пхожих ситуациях
		Matcher fsymb = symb.matcher(s1); // find math symbol
		// TODO [DK] 21.02.2012: А если не будет совпадения, то начальный и конечный символы какого совпадения оно будет
		// искать? лучше поставить здесь if() оператор с fSymb.find() в скобках, этот метод возвращает boolean
		fsymb.find(); // find math symbol
		int p1 = fsymb.start(); // container for the start of matching
		int p2 = fsymb.end(); // container for the end of matching
		String substr = s1.substring(p1, p2); // string for the math symbol
		char mathsymbol = substr.charAt(0); // get symbol from string
		// TODO [DK] 21.02.2012: тоже самое что и выше с симвовлом
		Matcher fnum = num.matcher(s1); // find first number
		fnum.find(); // find first number
		int n1 = fnum.start(); // container for the start of matching
		int n2 = fnum.end(); // container for the end of matching
		String subnum = s1.substring(n1, n2); // string for the first number
		int firstnum = Integer.parseInt(subnum); // first number

		int n3; // container for the second number
		int n4; // container for the second number
		// TODO [DK] 21.02.2012: От этой переменной можно избавиться
		String finalresult = ""; // string for the final result of calculating
		// TODO [DK] 21.02.2012: по code convenient нужно писать mathSymbol
		switch (mathsymbol) {
		// TODO [DK] 21.02.2012: смотри строку 21
			case '+':
				fnum.find(); // find second number
				n3 = fnum.start(); // start of matching
				n4 = fnum.end(); // end of matching
				// TODO [DK] 21.02.2012: code convenient: если имя переменной состоит из двух или более слов то они все
				// пишутся
				// маленькими буквами, но первая буква каждого слова начиная со второго пишется с большой буквы
				String sumsecond = s1.substring(n3, n4); // cut second number from string
				int sumsecondnum = Integer.parseInt(sumsecond); // make it int
				String resultsum = Integer.toString(calc.sum(firstnum, sumsecondnum)); // calculate sum
				// TODO [DK] 21.02.2012: finalResult нет смысла использовать, можно сразу передавать на выход,
				return (finalresult = firstnum + "+" + sumsecondnum + "=" + resultsum);
				// TODO [DK] 21.02.2012: смотри строку 21
			case '-':
				fnum.find();
				n3 = fnum.start();
				n4 = fnum.end();
				String subsecond = s1.substring(n3, n4);
				int subsecondnum = Integer.parseInt(subsecond); // second number
				String resultsub = Integer.toString(calc.subtract(firstnum, subsecondnum)); // calculate subtract
				return (finalresult = firstnum + "-" + subsecondnum + "=" + resultsub);
				// TODO [DK] 21.02.2012: смотри строку 21
			case '/':
				fnum.find();
				n3 = fnum.start();
				n4 = fnum.end();
				String divsecond = s1.substring(n3, n4);
				int divsecondnum = Integer.parseInt(divsecond); // second number
				String resultdiv = Double.toString(calc.divide(firstnum, divsecondnum)); // calculate dividing
				return (finalresult = firstnum + "/" + divsecondnum + "=" + resultdiv);
				// TODO [DK] 21.02.2012: смотри строку 21
			case '*':
				fnum.find();
				n3 = fnum.start();
				n4 = fnum.end();
				String multsecond = s1.substring(n3, n4);
				int multsecondnum = Integer.parseInt(multsecond); // second number
				String resultmult = Integer.toString(calc.multiply(firstnum, multsecondnum)); // calculate
																								// multiplication
				return (finalresult = firstnum + "*" + multsecondnum + "=" + resultmult);
				// TODO [DK] 21.02.2012: смотри строку 21
			case '!':
				String resultfactorial = Long.toString(calc.factorial(firstnum)); // calculate factorial
				return (finalresult = firstnum + "!" + "=" + resultfactorial);
				// TODO [DK] 21.02.2012: смотри строку 21
			case '^':
				fnum.find();
				n3 = fnum.start();
				n4 = fnum.end();
				String expsecond = s1.substring(n3, n4);
				int expsecondnum = Integer.parseInt(expsecond); // second number
				String resultexp = Long.toString(calc.exp(firstnum, expsecondnum)); // calculate exponentiation
				return (finalresult = firstnum + "^" + expsecondnum + "=" + resultexp);
				// TODO [DK] 21.02.2012: смотри строку 21
				// TODO [DK] 21.02.2012: вообщем корень квадратный это степень 1/2, тоесть достаточно использовать одну
				// функцию возведения в степень для двух случаев
			case '~':
				String resultsqrt = Double.toString(calc.sqrt(firstnum)); // calculate square root
				return (finalresult = firstnum + "~" + "=" + resultsqrt);

		}

		return finalresult;

	}
}
